package algorithm

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"fmt"

	paillier "github.com/roasbeef/go-go-gadget-paillier"
)

var (
	pSk *paillier.PrivateKey
	pPk *paillier.PublicKey
)

// 初始化 Paillier 密钥
func PaillierInit() {
	var err error
	pSk, err = paillier.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(err)
	}
	pPk = &pSk.PublicKey
	fmt.Println("PublicKey len", pSk.PublicKey.N.BitLen(), "PrivateKey len", pSk.N.BitLen())
}

// 分段加密长比特串
func PaillierEncryptLong(utf8Str string) ([]string, error) {
	plainData := []byte(utf8Str)
	chunkSize := 32 // 每块最大 32 字节（256 bit）
	var result []string

	for i := 0; i < len(plainData); i += chunkSize {
		end := min(i+chunkSize, len(plainData))
		chunk := plainData[i:end]

		ciphertext, err := paillier.Encrypt(pPk, chunk)
		if err != nil {
			return nil, err
		}
		encoded := base64.StdEncoding.EncodeToString(ciphertext)
		result = append(result, encoded)
	}
	return result, nil
}

// 分段解密密文串
func PaillierDecryptLong(encryptedChunks []string) (string, error) {
	var buffer bytes.Buffer

	for _, enc := range encryptedChunks {
		cipherBytes, err := base64.StdEncoding.DecodeString(enc)
		if err != nil {
			return "", err
		}
		m, err := paillier.Decrypt(pSk, cipherBytes)
		if err != nil {
			return "", err
		}
		buffer.Write(m)
	}
	return string(buffer.Bytes()), nil
}
